/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			env.cc
  \date			Jan 2012
  \author		TNick

  \brief		Contains the implementation of Env class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<main.h>

#include	<QDir>
#include	<QFile>
#include	<QFileInfo>
#include	<QDateTime>
#include	<QTextStream>

#include	"env.h"


/*  INCLUDES    ============================================================ */
//
//
//
//
/*  DEFINITIONS    --------------------------------------------------------- */


/*  DEFINITIONS    ========================================================= */
//
//
//
//
/*  DATA    ---------------------------------------------------------------- */

const char *			Env::predef_names_[PREDEV_MAX] = {
	"SOURCE_FILE",
	"SOURCE_PATH",
	"SOURCE_FILE_NAME",
	"CRT_PATH",
	"DAY",
	"HOUR",
	"MIN",
	"MONTH",
	"MSEC",
	"SEC",
	"YEAR"
};

extern int max_src_size_;

/*  DATA    ================================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/* ------------------------------------------------------------------------- */
Env::Env	( const QString & s_file )
{
	QDateTime now_dt = QDateTime::currentDateTime ();
	QDir crtd = QDir::current();
	QFile crtf ( crtd.absoluteFilePath( s_file ) );
	QFileInfo crtf_info( crtf );

	insert( predef_names_[PREDEV_SRCFILE], crtf.fileName() );
	insert( predef_names_[PREDEV_SRCPATH], crtf_info.absolutePath() );
	insert( predef_names_[PREDEV_SRCFILENAME], crtf_info.baseName() );
	insert( predef_names_[PREDEV_CRTPATH], crtd.absolutePath() );

	insert( predef_names_[PREDEV_YEAR],
			QString::number( now_dt.date().year() ) );
	insert( predef_names_[PREDEV_MONTH],
			QString::number( now_dt.date().month() ) );
	insert( predef_names_[PREDEV_DAY],
			QString::number( now_dt.date().day() ) );
	insert( predef_names_[PREDEV_HOUR],
			QString::number( now_dt.time().hour() ) );
	insert( predef_names_[PREDEV_MIN],
			QString::number( now_dt.time().minute() ) );
	insert( predef_names_[PREDEV_SEC],
			QString::number( now_dt.time().second() ) );
	insert( predef_names_[PREDEV_MSEC],
			QString::number( now_dt.time().msec() ) );

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
Env::~Env	( void )
{


}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool				Env::interpretLines	( QStringList & input_lines )
{
	int idx;
	int idx_end;
	bool b_append;
	QString	l_val;
	QString	r_val;


	/* iterate over each line */
	for ( int i = 0; i < input_lines.count(); i++ )
	{

		/* see if this is an assignment line */
		idx = input_lines.at( i ).indexOf( "=" );
		if ( idx == -1 )
		{
			/* at this time there is no input allowed that is not an assignment */
			ErrorReport( QObject::tr(
							 "File <%1> line %2:\n"
							 "Invalid input; it has to be an assignment.")
						 .arg( value( predef_names_[PREDEV_SRCFILE] ) )
						 .arg( i + 1 )
						 );
			return false;
		}

		/* get the left and right values */
		l_val = input_lines.at( i ).mid(0, idx).toUpper().trimmed();
		r_val = input_lines.at( i ).mid(idx + 1).trimmed();

		/* should we assign or append? */
		if ( l_val.endsWith( "+" ) )
		{
			b_append = true;
			l_val = l_val.mid(0, l_val.length() - 1).trimmed();
		}
		else
		{
			b_append = false;
		}

		/* if the key is not present, add it with an empty value */
		if ( !contains( l_val ) )
		{
			insert( l_val, "" );
		}


		/* replace the values of known variables in r_val */
		for(;;)	{
			idx = r_val.indexOf( "$" );
			if ( idx == -1 )
				break;
			for ( idx_end = idx+1; idx_end < r_val.length(); idx_end++ )
			{
				if ( r_val.at( idx_end ) == ' ' )
					break;
				if ( r_val.at( idx_end ) == '\t' )
					break;
			}
			//idx_end =

		}


	}

	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
Env *				Env::loadFile		( QString s_path )
{
	/* tokenise input */
	QStringList input_lines;
	if ( ! readSourceFile( s_path, input_lines ) )
	{
		return NULL;
	}
	else if ( input_lines.count() == 0 )
	{
		WarningReport(
					QString("File <%1> does not contain any input!")
					.arg( s_path )
					);
		return NULL;
	}

	/* create new environment */
	Env * env = new Env( s_path );

	/* feed input to this environment */
	if ( ! env->interpretLines( input_lines ) )
	{
		delete env;
		return NULL;
	}

	return env;
}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
bool				Env::readSourceFile		(
		QString s_path, QStringList & input_lines )
{
#define NORMAL_LINE 0
#define COMMENT_LINE 1
#define CONTIN_LINE 2

	QFile		src_file( s_path );
	/*QFileInfo	src_fileinfo( src_file );*/


	/* make shure the file is not too large */
	if ( src_file.size() > max_src_size_ )
	{
		ErrorReport( QObject::tr(
						 "Failed to read <%1> source file.\n"
						 "The size of the file (%2 bytes) is larger than "
						 "maximum allowed size (%3 bytes)")
					 .arg( src_file.fileName() )
					 .arg( src_file.size() )
					 .arg( max_src_size_ )
					 );
		return false;
	}
	/* open the file for reading */
	else if ( !src_file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		ErrorReport(
					QObject::tr( "Failed to read <%1> source file" )
					.arg( src_file.fileName() )
					);
		return false;
	}

	/* read the content of the file */
	QTextStream in( &src_file );

	QString tmp_line;
	QString line;
	int idx;
	int sts = NORMAL_LINE;
	while ( !in.atEnd() )
	{
		line = in.readLine().trimmed();
		idx = line.indexOf( "//" );
		if ( idx != -1 )
		{
			line = line.mid( 0, idx ).trimmed();
		}
		if ( sts != NORMAL_LINE )
		{
			line = tmp_line + line;
			tmp_line.clear();
		}

		if ( sts == COMMENT_LINE )
		{
			int idx2 = line.indexOf( "*/" );
			if ( idx2 == -1 )
			{
				tmp_line = line;
				line.clear();
				continue;
			}
			else
			{
				line = line.remove( 0, idx2 + 2 ).trimmed();
			}
		}
		sts = NORMAL_LINE;

		/* multiline comments */
		idx = line.indexOf( "/*" );
		while ( idx != -1 )
		{
			int idx2 = line.indexOf( "*/", idx );
			if ( idx2 == -1 )
			{
				tmp_line = line.mid( 0, idx ).trimmed();
				sts = COMMENT_LINE;
				break;
			}
			else
			{
				line = line.remove( idx, idx2 - idx + 2 ).trimmed();
				idx = line.indexOf( "/*" );
			}
		}

		/* add it to the list or see for continuation */
		if ( sts == NORMAL_LINE )
		{
			if ( line.endsWith( "\\" ) )
			{
				tmp_line = line.mid( 0, line.length() - 1 ).trimmed();
				sts = CONTIN_LINE;
			}
			else if ( line.length() > 0 )
			{
				input_lines.append( line );
			}
		}

		line.clear();
	}

	/* check normal exit */
	if ( sts != NORMAL_LINE )
	{
		if ( sts == COMMENT_LINE )
		{
			ErrorReport(
						QObject::tr( "<%1> source file has unmatched multiline comment marker" )
						.arg( src_file.fileName() )
						);
		}
		else if ( sts == COMMENT_LINE )
		{
			ErrorReport(
						QObject::tr( "<%1> source file has continuation line on last line" )
						.arg( src_file.fileName() )
						);
		}
		else
		{
			Q_ASSERT( false );
		}
		return false;
	}

	return true;
}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
